#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include "../include/lcd.h"







int fb_dev_init(const char* device,lcd_info *lcd_info)
{
    int fb_fd = -1; //LCD 设备文件描述符
    struct fb_var_screeninfo fb_var = {0};
    struct fb_fix_screeninfo fb_fix = {0};
    unsigned long screen_size;

    fb_fd = open(device,O_RDWR);
    if (0 > fb_fd) {
        fprintf(stderr, "open error: %s: %s\n", device, strerror(errno));
        return -1;
    }
    // 获取信息设定参数
    ioctl(fb_fd,FBIOGET_VSCREENINFO,&fb_var);
    ioctl(fb_fd,FBIOGET_FSCREENINFO,&fb_fix);

    screen_size = fb_fix.line_length * fb_var.yres;
    lcd_info->width = fb_var.xres;
    lcd_info->height = fb_var.yres;

    //内存映射
    lcd_info->screen_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
    if (MAP_FAILED == (void *)lcd_info->screen_base) {
        perror("mmap error");
        close(fb_fd);
        return -1;
    }
    /* LCD 背景刷白 */
    memset(lcd_info->screen_base, 0xFF, screen_size);
    return fb_fd;
}

// 一帧图像的长度
void YUYV_to_RGB5652(char *yuyv_data, lcd_info lcd_info,unsigned int length) {
    int i, j;
    int y0, u, y1, v;
    int r, g, b;
    unsigned int count = 0;
    unsigned int h = 0;
    //YUYV 是用4个字节描述两个像素
    //而RGB565呢 则是一个像素用了两个字节
    for (i = 0; i < length; i = i + 4) {
        // Extract YUV components from YUYV format
        y0 = yuyv_data[i];
        u = yuyv_data[i + 1] - 128;
        y1 = yuyv_data[i + 2];
        v = yuyv_data[i + 3] - 128;

        // Convert YUV to RGB
        // Convert YUV to RGB for first pixel using integer math
        r = y0 + ((v * 1436) >> 10); // 1.402 * 1024 = 1436
        g = y0 - ((u * 352) >> 10) - ((v * 731) >> 10); // 0.344136 * 1024 = 352, 0.714136 * 1024 = 731
        b = y0 + ((u * 1815) >> 10); // 1.772 * 1024 = 1815
        // Clamp RGB values
        r = (r > 255) ? 255 : (r < 0) ? 0 : r;
        g = (g > 255) ? 255 : (g < 0) ? 0 : g;
        b = (b > 255) ? 255 : (b < 0) ? 0 : b;
        // Pack RGB565 format
        unsigned short rgb565_pixel = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
        // 理论上来说是这样但实际要考虑width 和height
        // 一次性会增加两个字节
        //*(rgb565_buffer ++ ) = rgb565_pixel;
        lcd_info.screen_base[h * lcd_info.width + count] = rgb565_pixel;
        count++;
        // Process next YUV pair
        y0 = y1;
        // Convert YUV to RGB
        r = y0 + ((v * 1436) >> 10); // 1.402 * 1024 = 1436
        g = y0 - ((u * 352) >> 10) - ((v * 731) >> 10); // 0.344136 * 1024 = 352, 0.714136 * 1024 = 731
        b = y0 + ((u * 1815) >> 10); // 1.772 * 1024 = 1815
        // Clamp RGB values
        r = (r > 255) ? 255 : (r < 0) ? 0 : r;
        g = (g > 255) ? 255 : (g < 0) ? 0 : g;
        b = (b > 255) ? 255 : (b < 0) ? 0 : b;
        // Pack RGB565 format for second pixel
        rgb565_pixel = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);

        // 一次性会增加两个字节
        //*(rgb565_buffer ++ ) = rgb565_pixel;
        lcd_info.screen_base[h * lcd_info.width + count] = rgb565_pixel;
        count++;
        if(count == lcd_info.min_w) {
            count = 0;
            h++;
            if(h == lcd_info.min_h)
                break;
        }
    }
}